package com.metaverse.backend.converter;

import cn.hutool.core.bean.BeanUtil;
import com.metaverse.backend.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.transform.AliasedTupleSubsetResultTransformer;

import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
public class CustomBeanResultTransformer extends AliasedTupleSubsetResultTransformer {
    private static  CustomBeanResultTransformer INSTANCE;
    private Class resultClass;

    public CustomBeanResultTransformer(Class resultClass) {
        this.resultClass = resultClass;
    }

    public static CustomBeanResultTransformer create(Class resultClass){
        CustomBeanResultTransformer instance  = new CustomBeanResultTransformer(resultClass);
        INSTANCE = instance;
        return INSTANCE;
    }

    @Override
    public boolean isTransformedValueATupleElement(String[] aliases, int tupleLength) {
        return false;
    }

    @Override
    public Object transformTuple(Object[] tuple, String[] aliases) {
        try {
            Object result = this.resultClass.getDeclaredConstructor().newInstance();
            Map<String,Object> dataRow = new LinkedHashMap<>();
            for ( int i = 0; i < aliases.length; i++ ) {
                dataRow.put(aliases[i], tuple[i]);
            }

            BeanUtil.fillBeanWithMap(dataRow, result, true, null);

            return result;
        } catch (Exception e) {
            log.error("转换失败", e);
            throw new BusinessException("数据字段映射转换失败");
        }

    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }

        CustomBeanResultTransformer that = ( CustomBeanResultTransformer ) o;

        if ( ! resultClass.equals( that.resultClass ) ) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = resultClass.hashCode();
        result = 31 * result;
        return result;
    }

}
